/*
 * Copyright 2009, Team Mondegreen:
 * Brian Hsieh - bh2181@columbia.edu
 * Eugene Yao - eyy2102@columbia.edu
 * Jake Amonette - jaa2149@columbia.edu
 * Tal Giat - tg2235@colubia.edu
 * 
 * This file is part of AMFM (A Minimal Fractal Music Language), a language created for
 * fractal music as part of the Programming Languages and Translator class at Columbia university.
 *
 * For more details go to: http://code.google.com/p/amfm/
 * 
 * AMFM is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * at your option any later version.
 * 
 * AMFM is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with AMFM.  If not, see <http://www.gnu.org/licenses/>. 
 */

package com.myronmarston.music.settings;

/**
 * Specifies settings for what to apply self-similarity to, which type of self similarity, when to start the
 * piece and for how long to generate it
 * 
 * @author Jake
 */
public class AmFmSelfSimilaritySettings {
  private boolean continuousPlay;

  private boolean applyToPitch;

  private boolean applyToRhythm;

  private boolean applyToVolume;

  private int startBar;

  private int lengthInBars;

  /**
   * Constructor, sets all the self similarity properties, to use identity self similarity just set all
   * booleans to false
   * 
   * @param applyToPitch whether or not to apply self-similarity to the pitches
   * @param applyToRhythm whether or not to apply self-similarity to the rhythm
   * @param applyToVolume whether or not to apply self-similarity to the volume
   * @param startBar the bar to start playing the piece from
   * @param lengthInBars how many bars should the piece be played for
   * @throws IllegalArgumentException if startBar or lengthInBars are a number less than 1
   */
  public AmFmSelfSimilaritySettings(boolean continuousPlay, boolean applyToPitch, boolean applyToRhythm,
      boolean applyToVolume, int startBar, int lengthInBars) throws IllegalArgumentException {
    this.continuousPlay = continuousPlay;
    this.applyToPitch = applyToPitch;
    this.applyToRhythm = applyToRhythm;
    this.applyToVolume = applyToVolume;
    setStartBar(startBar);
    setLengthInBars(lengthInBars);
  }
  

  /**
   * Gets whether or not to apply the self similarities continuously until we reach the desired bars length to play,
   * or just to do the self-similarity once on the seed (once meaning on all notes in the seed), and then duplicate the
   * result multiple times till we get to the desired length.
   * @return whether or not to continuously apply self-similarity manipulations
   */
  public boolean isContinuousPlay() {
    return continuousPlay;
  }


  /**
   * Gets whether or not to apply self-similarity to the pitch of the germ notes. For example, if true, a germ
   * of G A B G would become G A B G, A B C A, B C D B, G A B G.
   * 
   * @return whether or not to apply self-similarity to the pitch
   */
  public boolean isApplyToPitch() {
    return applyToPitch;
  }

  /**
   * Gets whether or not to apply self-similarity to the rhythm of the germ. For example, if true, a germ
   * rhythm of 1/4 1/8 1/4 would become 1/4 1/8 1/4, 1/8 1/16 1/8, 1/4 1/8 1/4.
   * 
   * @return whether or not to apply self-similarity to the pitch
   */
  public boolean isApplyToRhythm() {
    return applyToRhythm;
  }

  /**
   * Gets whether or not to apply self-similarity to the volume of the germ notes. For example, if true, a
   * germ with a middle note accent would generate a middle section louder than the surrounding sections, with
   * the middle note of that section still louder.
   * 
   * @return whether or not to apply self-similarity to the volume of the germ notes
   */
  public boolean isApplyToVolume() {
    return applyToVolume;
  }

  /**
   * Gets whether or not self-similarity should be applied to something (pitch, rhythm or volume).
   * 
   * @return true if self-similarity should be applied to something
   */
  public boolean selfSimilarityShouldBeAppliedToSomething() {
    return this.isApplyToPitch() || this.isApplyToRhythm() || this.isApplyToVolume();
  }

  /**
   * @return the bar the piece should be starting at
   */
  public int getStartBar() {
    return startBar;
  }

  /**
   * Set the bar the piece should start at
   * 
   * @param startBar a number greater than 0
   * @throws IllegalArgumentException if the startBar is less than 1
   */
  private void setStartBar(int startBar) throws IllegalArgumentException {
    if (startBar < 1) {
      throw new IllegalArgumentException("start bar must be at least one");
    }
    this.startBar = startBar;
  }

  /**
   * @return the number of bars we want this piece to play
   */
  public int getLengthInBars() {
    return lengthInBars;
  }

  /**
   * Sets the number of bars we want the piece to play
   * 
   * @param lengthInBars number of bar to play the piece for
   * @throws IllegalArgumentException if the lengthInBars is less than 1
   */
  private void setLengthInBars(int lengthInBars) {
    if (lengthInBars < 1) {
      throw new IllegalArgumentException("length in bars must be at least one");
    }

    this.lengthInBars = lengthInBars;
  }
}